package com.sqlcheck.service.impl;

import com.sqlcheck.dto.ai.RuleVerificationRequest;
import com.sqlcheck.entity.CompatibilityRule;
import com.sqlcheck.entity.ScanResult;
import com.sqlcheck.entity.ScanTask;
import com.sqlcheck.entity.SqlStatement;
import com.sqlcheck.repository.CompatibilityRuleRepository;
import com.sqlcheck.repository.ScanTaskRepository;
import com.sqlcheck.repository.SqlStatementRepository;
import com.sqlcheck.service.AIEnhancementPromptManager;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * AI增强验证PROMPT管理器实现
 * 统一管理AI增强验证相关的PROMPT模板
 * 
 * @author Claude
 * @version v1.0
 * @since 2025-01-09
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AIEnhancementPromptManagerImpl implements AIEnhancementPromptManager {

    private final ScanTaskRepository scanTaskRepository;
    private final SqlStatementRepository sqlStatementRepository;
    private final CompatibilityRuleRepository compatibilityRuleRepository;

    // Token估算常量
    private static final double CHINESE_CHARS_PER_TOKEN = 2.0;
    private static final double ENGLISH_CHARS_PER_TOKEN = 0.75;

    // 模板文件路径
    private static final String AI_ENHANCEMENT_TEMPLATE = "prompt/ai-enhancement/ai-enhancement-template.md";
    private static final String OUTPUT_FORMAT_TEMPLATE = "prompt/ai-enhancement/output-format-template.md";

    @Override
    public String buildVerificationPrompt(Long taskId, List<ScanResult> ruleResults) {
        log.debug("构建AI增强验证PROMPT - 任务ID: {}, 规则结果数: {}", taskId, ruleResults.size());

        try {
            // 1. 获取任务信息
            ScanTask task = scanTaskRepository.selectById(taskId);
            if (task == null) {
                throw new IllegalArgumentException("任务不存在: " + taskId);
            }

            // 2. 按statement_number分组规则结果
            Map<Integer, List<ScanResult>> groupedResults = ruleResults.stream()
                    .filter(r -> r.getStatementNumber() != null && r.getRuleId() != null)
                    .collect(Collectors.groupingBy(ScanResult::getStatementNumber));

            // 3. 获取相关SQL语句
            List<SqlStatement> sqlStatements = sqlStatementRepository.selectList(
                    new QueryWrapper<SqlStatement>().eq("task_id", taskId));
            Map<Integer, SqlStatement> statementMap = sqlStatements.stream()
                    .collect(Collectors.toMap(SqlStatement::getStatementNumber, s -> s));

            // 4. 获取规则详细信息
            Set<String> ruleIds = ruleResults.stream()
                    .map(ScanResult::getRuleId)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());
            List<CompatibilityRule> rules = compatibilityRuleRepository.selectList(
                    new QueryWrapper<CompatibilityRule>().in("rule_id", ruleIds));
            Map<String, CompatibilityRule> ruleMap = rules.stream()
                    .collect(Collectors.toMap(CompatibilityRule::getRuleId, r -> r));

            // 5. 构建PROMPT变量
            Map<String, Object> variables = buildPromptVariables(task, groupedResults, statementMap, ruleMap);

            // 6. 加载并渲染模板
            String template = loadTemplate(AI_ENHANCEMENT_TEMPLATE);
            String prompt = renderTemplate(template, variables);

            log.debug("AI增强验证PROMPT构建完成 - 长度: {} 字符", prompt.length());
            return prompt;

        } catch (Exception e) {
            log.error("构建AI增强验证PROMPT失败", e);
            throw new RuntimeException("构建AI增强验证PROMPT失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String buildVerificationPrompt(RuleVerificationRequest request) {
        log.debug("基于请求对象构建AI增强验证PROMPT - 任务ID: {}", request.getTaskId());

        try {
            // 构建PROMPT变量
            Map<String, Object> variables = buildPromptVariables(request);

            // 加载并渲染模板
            String template = loadTemplate(AI_ENHANCEMENT_TEMPLATE);
            String prompt = renderTemplate(template, variables);

            log.debug("基于请求对象的AI增强验证PROMPT构建完成 - 长度: {} 字符", prompt.length());
            return prompt;

        } catch (Exception e) {
            log.error("基于请求对象构建AI增强验证PROMPT失败", e);
            throw new RuntimeException("构建AI增强验证PROMPT失败: " + e.getMessage(), e);
        }
    }

    @Override
    public String loadTemplate(String templateName) {
        try {
            ClassPathResource resource = new ClassPathResource(templateName);
            if (!resource.exists()) {
                log.warn("模板文件不存在，使用默认模板: {}", templateName);
                return getDefaultTemplate();
            }

            String template = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
            log.debug("成功加载PROMPT模板: {} (长度: {} 字符)", templateName, template.length());
            return template;

        } catch (IOException e) {
            log.error("加载PROMPT模板失败: {}", templateName, e);
            log.warn("使用默认模板作为备用");
            return getDefaultTemplate();
        }
    }

    @Override
    public String renderTemplate(String template, Map<String, Object> variables) {
        if (template == null || template.isEmpty()) {
            throw new IllegalArgumentException("模板内容不能为空");
        }

        String result = template;
        for (Map.Entry<String, Object> entry : variables.entrySet()) {
            String placeholder = "{" + entry.getKey() + "}";
            String value = entry.getValue() != null ? entry.getValue().toString() : "";
            result = result.replace(placeholder, value);
        }

        return result;
    }

    @Override
    public int estimateTokenCount(String prompt) {
        if (prompt == null || prompt.isEmpty()) {
            return 0;
        }

        int chineseChars = 0;
        int englishChars = 0;

        for (char ch : prompt.toCharArray()) {
            if (ch >= 0x4e00 && ch <= 0x9fff) { // 中文字符范围
                chineseChars++;
            } else if (Character.isLetterOrDigit(ch) || Character.isWhitespace(ch)) {
                englishChars++;
            }
        }

        int estimatedTokens = (int) Math.ceil(chineseChars / CHINESE_CHARS_PER_TOKEN +
                englishChars / ENGLISH_CHARS_PER_TOKEN);

        return Math.max(1, estimatedTokens);
    }

    @Override
    public int getBasePromptTokens(Long taskId, String sourceDbType, String targetDbType) {
        // 构建基础PROMPT（不包含具体SQL内容）
        Map<String, Object> baseVariables = new HashMap<>();
        baseVariables.put("taskId", taskId);
        baseVariables.put("sourceDbType", sourceDbType);
        baseVariables.put("targetDbType", targetDbType);
        baseVariables.put("analysisTimestamp", LocalDateTime.now().toString());
        baseVariables.put("sqlStatements", ""); // 空的SQL内容

        String template = loadTemplate(AI_ENHANCEMENT_TEMPLATE);
        String basePrompt = renderTemplate(template, baseVariables);

        return estimateTokenCount(basePrompt);
    }

    /**
     * 构建PROMPT变量映射
     */
    private Map<String, Object> buildPromptVariables(ScanTask task,
            Map<Integer, List<ScanResult>> groupedResults,
            Map<Integer, SqlStatement> statementMap,
            Map<String, CompatibilityRule> ruleMap) {
        Map<String, Object> variables = new HashMap<>();

        // 基础信息
        variables.put("taskId", task.getId());
        variables.put("sourceDbType", task.getSourceDbType());
        variables.put("targetDbType", task.getTargetDbType());
        variables.put("analysisTimestamp", LocalDateTime.now().toString());

        // 构建SQL语句和规则信息
        StringBuilder sqlStatementsBuilder = new StringBuilder();
        for (Map.Entry<Integer, List<ScanResult>> entry : groupedResults.entrySet()) {
            Integer statementNumber = entry.getKey();
            List<ScanResult> issues = entry.getValue();
            SqlStatement sqlStatement = statementMap.get(statementNumber);

            if (sqlStatement != null) {
                sqlStatementsBuilder.append("### SQL语句 #").append(statementNumber).append("\n");
                sqlStatementsBuilder.append("**SQL内容**:\n");
                sqlStatementsBuilder.append("```sql\n").append(sqlStatement.getContent()).append("\n```\n\n");

                // 添加规则检测结果
                sqlStatementsBuilder.append("**规则引擎检测到的问题**:\n");
                for (int i = 0; i < issues.size(); i++) {
                    ScanResult issue = issues.get(i);
                    CompatibilityRule rule = ruleMap.get(issue.getRuleId());

                    sqlStatementsBuilder.append("问题").append(i + 1).append(" [").append(issue.getRuleId())
                            .append("]: ");
                    sqlStatementsBuilder.append(issue.getRuleName()).append(" - ");
                    sqlStatementsBuilder.append("[").append(rule != null ? rule.getCategory() : "UNKNOWN");
                    sqlStatementsBuilder.append("/").append(issue.getSeverity()).append("] ");
                    sqlStatementsBuilder.append(issue.getIssueDescription()).append("\n");
                }
                sqlStatementsBuilder.append("---\n\n");
            }
        }

        variables.put("sqlStatements", sqlStatementsBuilder.toString());

        // 加载输出格式要求
        String outputFormatTemplate = loadTemplate(OUTPUT_FORMAT_TEMPLATE);
        variables.put("outputFormat", outputFormatTemplate);

        return variables;
    }

    /**
     * 基于请求对象构建PROMPT变量映射
     */
    private Map<String, Object> buildPromptVariables(RuleVerificationRequest request) {
        Map<String, Object> variables = new HashMap<>();

        // 基础信息
        variables.put("taskId", request.getTaskId());
        variables.put("sourceDbType", request.getSourceDbType());
        variables.put("targetDbType", request.getTargetDbType());
        variables.put("analysisTimestamp", LocalDateTime.now().toString());

        // 构建SQL语句信息
        StringBuilder sqlStatementsBuilder = new StringBuilder();
        for (RuleVerificationRequest.StatementVerificationItem statement : request.getStatements()) {
            sqlStatementsBuilder.append("### SQL语句 #").append(statement.getStatementNumber()).append("\n");
            sqlStatementsBuilder.append("**SQL内容**:\n");
            sqlStatementsBuilder.append("```sql\n").append(statement.getSqlContent()).append("\n```\n\n");

            // 添加规则检测结果
            sqlStatementsBuilder.append("**规则引擎检测到的问题**:\n");
            for (int i = 0; i < statement.getDetectedIssues().size(); i++) {
                RuleVerificationRequest.RuleIssueItem issue = statement.getDetectedIssues().get(i);
                sqlStatementsBuilder.append("问题").append(i + 1).append(" [").append(issue.getRuleId()).append("]: ");
                sqlStatementsBuilder.append(issue.getRuleName()).append(" - ");
                sqlStatementsBuilder.append("[").append(issue.getCategory()).append("/").append(issue.getSeverity())
                        .append("] ");
                sqlStatementsBuilder.append(issue.getIssueDescription()).append("\n");
            }
            sqlStatementsBuilder.append("---\n\n");
        }

        variables.put("sqlStatements", sqlStatementsBuilder.toString());

        // 加载输出格式要求
        String outputFormatTemplate = loadTemplate(OUTPUT_FORMAT_TEMPLATE);
        variables.put("outputFormat", outputFormatTemplate);

        return variables;
    }

    /**
     * 获取默认的PROMPT模板（备用）
     */
    private String getDefaultTemplate() {
        return "你是一个资深的数据库迁移专家，专门负责验证SQL兼容性规则分析结果。\n\n" +
                "**任务信息**:\n" +
                "- 任务ID: {taskId}\n" +
                "- 源数据库: {sourceDbType}\n" +
                "- 目标数据库: {targetDbType}\n" +
                "- 分析时间: {analysisTimestamp}\n\n" +
                "**需要验证的SQL语句和规则结果**:\n\n" +
                "{sqlStatements}\n\n" +
                "**输出格式要求**:\n" +
                "{outputFormat}";
    }
}